#include <stdio.h>
#include <stdint.h>
#include "lv_drv_conf.h"
#if USE_SDL
#include "lv_drivers/sdl/sdl.h"
#elif USE_DRM
#include "lv_drivers/display/drm.h"
#endif
#if USE_EVDEV
#include "lv_drivers/indev/evdev.h"
#endif
#include "lvgl/lvgl.h"
#include "lvgl/demos/lv_demos.h"
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <sys/time.h>
#include <stdlib.h>
#include "app.h"
#include "ui.h"


int main(int argc, char *argv[])
{
#if USE_SDL
    /*LittlevGL init*/
    lv_init();

    sdl_init();

    lv_disp_drv_t disp_drv;
	lv_disp_drv_init(&disp_drv);
       
	disp_drv.hor_res = SDL_HOR_RES;
	disp_drv.ver_res = SDL_VER_RES;
    
	// Allocate LVGL buffers
    void * lvgl_buf1 = malloc(disp_drv.hor_res * disp_drv.ver_res * (LV_COLOR_SIZE/8));
    if (!lvgl_buf1)
        return -1;
    void *lvgl_buf2 = malloc(disp_drv.hor_res * disp_drv.ver_res * (LV_COLOR_SIZE/8));
    if (!lvgl_buf2)
        return -1;

    static lv_disp_draw_buf_t disp_buf;
    lv_disp_draw_buf_init(&disp_buf, lvgl_buf1, lvgl_buf2, disp_drv.hor_res * disp_drv.ver_res);
    
    disp_drv.draw_buf   = &disp_buf;
    disp_drv.flush_cb = sdl_display_flush;
    disp_drv.full_refresh   = 0;
    lv_disp_drv_register(&disp_drv);
    
	static lv_indev_drv_t indev_drv_1;
    lv_indev_drv_init(&indev_drv_1); /*Basic initialization*/
    indev_drv_1.type = LV_INDEV_TYPE_POINTER;

    /*This function will be called periodically (by the library) to get the mouse position and state*/
    indev_drv_1.read_cb = sdl_mouse_read;
	#if 1
	lv_indev_drv_register(&indev_drv_1);
	#else
    lv_indev_t *mouse_indev = lv_indev_drv_register(&indev_drv_1);

    /*Set a cursor for the mouse*/
    LV_IMG_DECLARE(mouse_cursor_icon)
    lv_obj_t * cursor_obj = lv_img_create(lv_scr_act()); /*Create an image object for the cursor */
    lv_img_set_src(cursor_obj, &mouse_cursor_icon);           /*Set the image source*/
    lv_indev_set_cursor(mouse_indev, cursor_obj);             /*Connect the image  object to the driver*/
	#endif
#elif USE_DRM
    uint32_t dpi = 0;

    /*LittlevGL init*/
    lv_init();

    drm_init();

    lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
       
    drm_get_sizes(&disp_drv.hor_res, &disp_drv.ver_res, &dpi);

    // Allocate LVGL buffers
    void * lvgl_buf1 = malloc(disp_drv.hor_res * disp_drv.ver_res * (LV_COLOR_SIZE/8));
    if (!lvgl_buf1)
        return -1;
    void *lvgl_buf2 = malloc(disp_drv.hor_res * disp_drv.ver_res * (LV_COLOR_SIZE/8));
    if (!lvgl_buf2)
        return -1;

    static lv_disp_draw_buf_t disp_buf;
    lv_disp_draw_buf_init(&disp_buf, lvgl_buf1, lvgl_buf2, disp_drv.hor_res * disp_drv.ver_res);

    disp_drv.draw_buf   = &disp_buf;
    disp_drv.flush_cb = drm_flush;
    disp_drv.wait_cb = drm_wait_vsync;
    disp_drv.full_refresh   = 1;
    lv_disp_drv_register(&disp_drv);
#endif

#if 0//USE_EVDEV
    evdev_init();
    static lv_indev_drv_t indev_drv_1;
    lv_indev_drv_init(&indev_drv_1); /*Basic initialization*/
    indev_drv_1.type = LV_INDEV_TYPE_POINTER;

    /*This function will be called periodically (by the library) to get the mouse position and state*/
    indev_drv_1.read_cb = evdev_read;
    indev_drv_1.feedback_cb = ui_input_feedback;
	#if 1
	lv_indev_drv_register(&indev_drv_1);
	#else
    lv_indev_t *mouse_indev = lv_indev_drv_register(&indev_drv_1);

    /*Set a cursor for the mouse*/
    LV_IMG_DECLARE(mouse_cursor_icon)
    lv_obj_t * cursor_obj = lv_img_create(lv_scr_act()); /*Create an image object for the cursor */
    lv_img_set_src(cursor_obj, &mouse_cursor_icon);           /*Set the image source*/
    lv_indev_set_cursor(mouse_indev, cursor_obj);             /*Connect the image  object to the driver*/
	#endif
#endif
	/*Create a Demo*/
    app_init();
    //lv_demo_widgets();

    /*Handle LitlevGL tasks (tickless mode)*/
    while(1) {
        lv_timer_handler();
        app_handler();
        usleep(50000);
    }

    return 0;
}
    
/*Set in lv_conf.h as `LV_TICK_CUSTOM_SYS_TIME_EXPR`*/
uint32_t custom_tick_get(void)
{
    static uint64_t start_ms = 0;
    if(start_ms == 0) {
        struct timeval tv_start;
        gettimeofday(&tv_start, NULL);
        start_ms = (tv_start.tv_sec * 1000000 + tv_start.tv_usec) / 1000;
    }

    struct timeval tv_now;
    gettimeofday(&tv_now, NULL);
    uint64_t now_ms;
    now_ms = (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000;

    uint32_t time_ms = now_ms - start_ms;
    return time_ms;
}

